// 这个代码可以退休了
// 用工具simple-element-resize-detector.js,用法更简单，性能更好


// 元素监听
// 使用定时器实现监听
// 轮询时间为300毫秒一次
// 全局使用一个定时器，避免定时器带来过大的性能开销

import htmlElementUtils from "./htmlElementUtils";

export type ListenElCallBack = (el: HTMLElement, oldHeight: string, oldWidth: string) => void

interface ListenEl {
  el: HTMLElement
  oldHeight: string
  oldWidth: string
  callBackList: ListenElCallBack[]
}

export class ElSizeListen {
  /**
   * 存放监听的元素
   * @private
   */
  private static listenEls: ListenEl[] = []
  /**
   * 监听的定时器
   * @private
   */
  private static setTimeListener: NodeJS.Timer | null = null
  /**
   * 监听元素还在不在body中，不在body中移除
   * @private
   */
  private static setTimeElInBody: NodeJS.Timer | null = null

  /**
   * 添加监听，添加监听的同时会执行一次
   * @param el
   * @param callBack
   * @param executeImmediately callback是否立即执行一次
   */
  static addListen(el: HTMLElement, callBack: ListenElCallBack, executeImmediately: boolean = true) {
    if (executeImmediately) {
      callBack(el, htmlElementUtils.getStyle(el, 'height'), htmlElementUtils.getStyle(el, 'width'))
    }
    const listenEl = ElSizeListen.listenEls.findIndex(i => i.el === el);
    if (listenEl === -1) {
      ElSizeListen.listenEls.push({
        el,
        oldHeight: htmlElementUtils.getStyle(el, 'height'),
        oldWidth: htmlElementUtils.getStyle(el, 'width'),
        callBackList: [callBack]
      })
    } else {
      ElSizeListen.listenEls[listenEl].callBackList.push(callBack)
    }
    if (ElSizeListen.listenEls.length === 1) {
      if (ElSizeListen.setTimeListener === null) {
        ElSizeListen.setTimeListener = setInterval(() => {
          ElSizeListen.listenEls.forEach(i => {
            if (htmlElementUtils.getStyle(i.el, 'width') !== i.oldWidth || htmlElementUtils.getStyle(i.el, 'height') !== i.oldHeight) { // 大小变动了
              i.callBackList.forEach(call => {
                call(i.el, i.oldHeight, i.oldWidth)
              })
              i.oldHeight = htmlElementUtils.getStyle(i.el, 'height')
              i.oldWidth = htmlElementUtils.getStyle(i.el, 'width')
            }
          })
        }, 300) // 300毫秒执行一次
      }
      if (ElSizeListen.setTimeElInBody === null) {
        ElSizeListen.setTimeElInBody = setInterval(() => {
          ElSizeListen.listenEls.filter(i => {
            if (i.el === document.body) {
              return false
            }
            return !htmlElementUtils.hasChildren(document.body, i.el);
          }).forEach(i => {
            ElSizeListen.removeListenAll(i.el)
          })
        }, 5000) // 5秒执行一次
      }
    }
  }

  /**
   * 移除所有监听
   * @param el
   */
  static removeListenAll(el: HTMLElement) {
    const listenEl = ElSizeListen.listenEls.findIndex(i => i.el === el);
    ElSizeListen.__removeListenAll(listenEl)
  }

  /**
   * 移除所有
   * @param findIndex
   * @private
   */
  private static __removeListenAll(findIndex: number = -1) {
    if (findIndex > -1) {
      ElSizeListen.listenEls.splice(findIndex, 1)
    }
    if (ElSizeListen.listenEls.length === 0) {
      ElSizeListen.__clearInterval('setTimeListener')
      ElSizeListen.__clearInterval('setTimeElInBody')
    }
  }


  /**
   * 清除内部定时器
   * @param name
   * @private
   */
  private static __clearInterval(name: string = '') {
    if (ElSizeListen[name]) {
      clearInterval(ElSizeListen[name])
      ElSizeListen[name] = null
    }
  }

  /**
   * 移除监听
   * @param el
   * @param callBack
   */
  static removeListen(el: HTMLElement, callBack: ListenElCallBack) {
    const listenElIndex = ElSizeListen.listenEls.findIndex(i => i.el === el);
    if (listenElIndex > -1) {
      const listenEl = ElSizeListen.listenEls[listenElIndex];
      const findIndex = listenEl.callBackList.findIndex(i => i === callBack);
      if (findIndex > -1) {
        listenEl.callBackList.splice(findIndex, 1)
        if (listenEl.callBackList.length === 0) {
          ElSizeListen.__removeListenAll(listenElIndex)
        }
      }
    }
  }
}
